<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>重力反转迷宫</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background: #222;
            font-family: 'Arial', sans-serif;
        }

        canvas {
            display: block;
            cursor: pointer;
        }

        #ui {
            position: absolute;
            top: 20px;
            left: 20px;
            color: white;
            font-family: 'Arial', sans-serif;
            background: rgba(0, 0, 0, 0.6);
            padding: 15px;
            border-radius: 10px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
        }

        #timeDisplay {
            position: absolute;
            top: 20px;
            right: 20px;
            color: white;
            font-family: 'Arial', sans-serif;
            background: rgba(0, 0, 0, 0.6);
            padding: 15px;
            border-radius: 10px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
            font-size: 16px;
        }

        #timeDisplay span {
            color: #FF5555;
            font-weight: bold;
            margin-left: 5px;
        }

        #ui div {
            margin: 8px 0;
            font-size: 16px;
            display: flex;
            align-items: center;
        }

        #ui span {
            margin-left: 10px;
            font-weight: bold;
            color: #FF5555;
        }

        @keyframes glitch {
            0% {
                text-shadow: 0.05em 0 0 #FF5555, -0.05em -0.025em 0 #55FF55,
                             -0.025em 0.05em 0 #5555FF;
            }
            14% {
                text-shadow: 0.05em 0 0 #FF5555, -0.05em -0.025em 0 #55FF55,
                             -0.025em 0.05em 0 #5555FF;
            }
            15% {
                text-shadow: -0.05em -0.025em 0 #FF5555, 0.025em 0.025em 0 #55FF55,
                             -0.05em -0.05em 0 #5555FF;
            }
            49% {
                text-shadow: -0.05em -0.025em 0 #FF5555, 0.025em 0.025em 0 #55FF55,
                             -0.05em -0.05em 0 #5555FF;
            }
            50% {
                text-shadow: 0.025em 0.05em 0 #FF5555, 0.05em 0 0 #55FF55,
                             0 -0.05em 0 #5555FF;
            }
            99% {
                text-shadow: 0.025em 0.05em 0 #FF5555, 0.05em 0 0 #55FF55,
                             0 -0.05em 0 #5555FF;
            }
            100% {
                text-shadow: -0.025em 0 0 #FF5555, -0.025em -0.025em 0 #55FF55,
                             -0.025em -0.05em 0 #5555FF;
            }
        }

        @keyframes scanline {
            0% {
                transform: translateY(-100%);
            }
            100% {
                transform: translateY(100%);
            }
        }

        @keyframes pulse {
            0% {
                box-shadow: 0 0 0 0 rgba(255, 85, 85, 0.4);
            }
            70% {
                box-shadow: 0 0 0 20px rgba(255, 85, 85, 0);
            }
            100% {
                box-shadow: 0 0 0 0 rgba(255, 85, 85, 0);
            }
        }

        @keyframes glitch-1 {
            0% {
                clip-path: inset(20% 0 30% 0);
            }
            20% {
                clip-path: inset(60% 0 10% 0);
            }
            40% {
                clip-path: inset(40% 0 50% 0);
            }
            60% {
                clip-path: inset(80% 0 5% 0);
            }
            80% {
                clip-path: inset(10% 0 70% 0);
            }
            100% {
                clip-path: inset(30% 0 20% 0);
            }
        }

        @keyframes glitch-2 {
            0% {
                clip-path: inset(15% 0 35% 0);
            }
            20% {
                clip-path: inset(55% 0 15% 0);
            }
            40% {
                clip-path: inset(45% 0 45% 0);
            }
            60% {
                clip-path: inset(75% 0 10% 0);
            }
            80% {
                clip-path: inset(15% 0 65% 0);
            }
            100% {
                clip-path: inset(25% 0 25% 0);
            }
        }

        #startMenu {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0, 0, 0, 0.85);
            color: white;
            padding: 30px 60px;
            border-radius: 15px;
            text-align: center;
            box-shadow: 0 0 30px rgba(255, 85, 85, 0.3);
            border: 2px solid rgba(255, 85, 85, 0.3);
            min-width: 400px;
            max-width: 600px;
            overflow: visible;
            z-index: 1000;
        }

        #startMenu::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            height: 2px;
            background: linear-gradient(90deg, 
                transparent, 
                #FF5555, 
                #55FF55, 
                #5555FF, 
                transparent
            );
            animation: scanline 3s linear infinite;
        }

        #startMenu::after {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: repeating-linear-gradient(
                0deg,
                rgba(0, 0, 0, 0.15),
                rgba(0, 0, 0, 0.15) 1px,
                transparent 1px,
                transparent 2px
            );
            pointer-events: none;
        }

        #startMenu h1 {
            margin-bottom: 20px;
            font-size: 2.5em;
            color: #FF5555;
            text-shadow: 0 0 10px rgba(255, 85, 85, 0.5);
            animation: glitch 3s infinite;
            letter-spacing: 2px;
            position: relative;
        }

        #startMenu h1::before,
        #startMenu h1::after {
            content: attr(data-text);
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }

        #startMenu h1::before {
            left: 2px;
            text-shadow: -2px 0 #55FF55;
            animation: glitch-1 2s infinite linear alternate-reverse;
        }

        #startMenu h1::after {
            left: -2px;
            text-shadow: 2px 0 #5555FF;
            animation: glitch-2 3s infinite linear alternate-reverse;
        }

        .game-rules {
            text-align: left;
            margin: 15px 0;
            padding: 15px;
            background: rgba(255, 85, 85, 0.1);
            border-radius: 10px;
            border: 1px solid rgba(255, 85, 85, 0.2);
            max-height: 250px;
            overflow-y: auto;
        }

        .game-rules::-webkit-scrollbar {
            width: 8px;
        }

        .game-rules::-webkit-scrollbar-track {
            background: rgba(255, 85, 85, 0.1);
            border-radius: 4px;
        }

        .game-rules::-webkit-scrollbar-thumb {
            background: rgba(255, 85, 85, 0.3);
            border-radius: 4px;
        }

        .game-rules::-webkit-scrollbar-thumb:hover {
            background: rgba(255, 85, 85, 0.5);
        }

        .game-rules h2 {
            color: #FF5555;
            margin-bottom: 12px;
            font-size: 1.3em;
            text-align: center;
            position: sticky;
            top: 0;
            background: rgba(0, 0, 0, 0.85);
            padding: 5px 0;
            z-index: 1;
        }

        .game-rules ul {
            list-style: none;
            padding: 0;
            margin: 0;
        }

        .game-rules li {
            margin: 8px 0;
            padding-left: 20px;
            position: relative;
            line-height: 1.3;
            font-size: 0.95em;
        }

        .game-rules li::before {
            content: '►';
            position: absolute;
            left: 0;
            color: #FF5555;
            font-size: 0.9em;
        }

        .menu-btn {
            margin: 15px 0 5px 0;
            padding: 12px 25px;
            background: #FF5555;
            border: none;
            border-radius: 8px;
            color: white;
            cursor: pointer;
            font-size: 16px;
            transition: all 0.3s ease;
            box-shadow: 0 0 15px rgba(255, 85, 85, 0.3);
            position: relative;
            overflow: hidden;
            text-transform: uppercase;
            letter-spacing: 1px;
            width: 200px;
        }

        .menu-btn::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(
                90deg,
                transparent,
                rgba(255, 255, 255, 0.2),
                transparent
            );
            transition: 0.5s;
        }

        .menu-btn:hover {
            background: #FF3333;
            transform: translateY(-2px);
            box-shadow: 0 0 20px rgba(255, 85, 85, 0.5);
            animation: pulse 1.5s infinite;
        }

        .menu-btn:hover::before {
            left: 100%;
        }

        .menu-btn:active {
            transform: translateY(0);
            box-shadow: 0 0 10px rgba(255, 85, 85, 0.3);
        }

        .cyber-grid {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: 
                linear-gradient(transparent 0%, rgba(255, 85, 85, 0.05) 2%, transparent 3%),
                linear-gradient(90deg, transparent 0%, rgba(255, 85, 85, 0.05) 2%, transparent 3%);
            background-size: 50px 50px;
            pointer-events: none;
            z-index: -1;
        }

        .difficulty-select {
            margin: 20px 0;
            padding: 15px;
            background: rgba(255, 85, 85, 0.1);
            border-radius: 10px;
            border: 1px solid rgba(255, 85, 85, 0.2);
        }

        .difficulty-select h2 {
            color: #FF5555;
            margin-bottom: 15px;
            font-size: 1.5em;
        }

        .difficulty-buttons {
            display: flex;
            justify-content: center;
            gap: 10px;
        }

        .difficulty-btn {
            padding: 10px 20px;
            background: rgba(255, 85, 85, 0.2);
            border: 1px solid rgba(255, 85, 85, 0.3);
            border-radius: 5px;
            color: white;
            cursor: pointer;
            transition: all 0.3s ease;
        }

        .difficulty-btn:hover {
            background: rgba(255, 85, 85, 0.3);
            transform: translateY(-2px);
        }

        .difficulty-btn.active {
            background: #FF5555;
            box-shadow: 0 0 15px rgba(255, 85, 85, 0.5);
        }

        #gameOver {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0, 0, 0, 0.9);
            color: white;
            padding: 40px;
            border-radius: 15px;
            text-align: center;
            box-shadow: 0 0 30px rgba(255, 85, 85, 0.3);
            border: 2px solid rgba(255, 85, 85, 0.3);
            min-width: 300px;
            z-index: 1000;
            display: none;
        }

        #gameOver h2 {
            color: #FF5555;
            font-size: 2em;
            margin-bottom: 20px;
            text-shadow: 0 0 10px rgba(255, 85, 85, 0.5);
        }

        #gameOver p {
            font-size: 1.2em;
            margin: 15px 0;
        }

        #gameOver .menu-btn {
            margin: 10px;
            display: inline-block;
        }
    </style>

    <!-- 引入 ECharts -->
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script>
</head>

<body>
    <div class="cyber-grid"></div>
    <canvas id="gameCanvas"></canvas>

    <!-- 开始菜单 -->
    <div id="startMenu">
        <h1 data-text="重力反转迷宫">重力反转迷宫</h1>
        
        <div class="game-rules">
            <h2>游戏规则</h2>
            <ul>
                <li>使用空格键控制小球的重力方向</li>
                <li>避开蓝色墙壁，碰到墙壁游戏结束</li>
                <li>进入棕色重力场会改变重力方向</li>
                <li>到达绿色终点即可通关</li>
                <li>每关有2分钟时间限制</li>
                <li>重力反转次数有限，请合理使用</li>
            </ul>
        </div>

        <button id="startBtn" class="menu-btn">开始游戏</button>
    </div>

    <!-- UI 状态 -->
    <div id="ui">
        <div>重力方向: <span id="gravityDisplay">↓</span></div>
        <div>使用次数: <span id="flipsLeft">30</span></div>
        <div>当前关卡: <span id="currentLevel">1</span></div>
    </div>

    <!-- 游戏结束界面 -->
    <div id="gameOver">
        <h2 id="resultTitle">通关成功!</h2>
        <p>已通关：<span id="passedLevels">0</span> 关</p>
        <button id="restartBtn" class="menu-btn">重新开始当前关卡</button>
        <button id="nextLevelBtn" class="menu-btn">进入下一关</button>
        <button id="exitBtn" class="menu-btn">退出游戏</button>
    </div>

    <!-- 时间显示 -->
    <div id="timeDisplay">
        时间: <span>2:00</span>
    </div>

    <script>
        const COLORS = {
            ball: '#FF5555',
            wall: '#334466',
            goal: '#55FF55',
            gravityField: '#FFAA33',
            text: '#FFFFFF'
        };

        // 添加音效
        const SOUNDS = {
            flip: new Audio('data:audio/wav;base64,UklGRl9vT19XQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YU'),
            hit: new Audio('data:audio/wav;base64,UklGRl9vT19XQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YU'),
            goal: new Audio('data:audio/wav;base64,UklGRl9vT19XQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YU'),
            gameOver: new Audio('data:audio/wav;base64,UklGRl9vT19XQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YU')
        };

        class GravityMaze {
            constructor() {
                this.canvas = document.getElementById('gameCanvas');
                this.ctx = this.canvas.getContext('2d');

                // UI 元素引用
                this.uiElements = {
                    gravity: document.getElementById('gravityDisplay'),
                    flips: document.getElementById('flipsLeft'),
                    level: document.getElementById('currentLevel'),
                    gameOver: document.getElementById('gameOver'),
                    resultTitle: document.getElementById('resultTitle'),
                    restartBtn: document.getElementById('restartBtn'),
                    nextLevelBtn: document.getElementById('nextLevelBtn'),
                    exitBtn: document.getElementById('exitBtn'),
                    passedLevels: document.getElementById('passedLevels'),
                    startMenu: document.getElementById('startMenu'),
                    startBtn: document.getElementById('startBtn')
                };

                // 初始化游戏参数
                this.gravity = { x: 0, y: 1 };
                this.gravityFields = [];
                this.walls = [];
                this.flipsRemaining = 30;
                this.isGameOver = false;
                this.trail = [];
                this.lastFlipTime = 0;

                this.currentLevel = 1;
                this.maxLevels = 5;
                this.passedLevels = 0;

                // 添加时间和尝试次数记录
                this.levelStartTime = 0;
                this.totalLevelTime = 0;
                this.levelAttempts = 0;
                this.isFirstAttempt = true;

                // 设置画布尺寸
                this.resize();
                window.addEventListener('resize', () => this.resize());

                // 初始化球和目标
                this.ball = new Ball(
                    this.canvas.width * 0.2,
                    this.canvas.height * 0.5,
                    15
                );

                this.goal = {
                    x: this.canvas.width * 0.8,
                    y: this.canvas.height * 0.5,
                    radius: 20
                };

                // 事件监听
                document.addEventListener('keydown', (e) => this.handleInput(e));
                this.uiElements.startBtn.addEventListener('click', () => this.startGame());
                this.uiElements.restartBtn.addEventListener('click', () => this.resetGame());
                this.uiElements.nextLevelBtn.addEventListener('click', () => this.nextLevel());
                this.uiElements.exitBtn.addEventListener('click', () => this.exitGame());

                // 初始隐藏游戏结束界面
                this.uiElements.gameOver.style.display = 'none';
                this.uiElements.startMenu.style.display = 'block';

                this.timeLimit = 120; // 2分钟时间限制
                this.timeRemaining = this.timeLimit;
                this.lastTimeUpdate = performance.now();

                // 添加时间显示元素
                this.timeDisplay = document.createElement('div');
                this.timeDisplay.id = 'timeDisplay';
                this.timeDisplay.innerHTML = '时间: <span>2:00</span>';
                document.body.appendChild(this.timeDisplay);
            }

            resize() {
                this.canvas.width = window.innerWidth;
                this.canvas.height = window.innerHeight;
                
                // 重新生成关卡以适应新的尺寸
                if (this.ball) {
                    this.generateLevel();
                }
            }

            generateLevel() {
                this.walls = [];
                this.gravityFields = [];

                // 边界墙
                this.walls.push(...[
                    { x: 0, y: 0, width: this.canvas.width, height: 20 },
                    { x: 0, y: this.canvas.height - 20, width: this.canvas.width, height: 20 },
                    { x: 0, y: 0, width: 20, height: this.canvas.height },
                    { x: this.canvas.width - 20, y: 0, width: 20, height: this.canvas.height }
                ]);

                // 定义安全区域
                const safeRadius = 50;
                const startX = this.canvas.width * 0.2;
                const startY = this.canvas.height * 0.5;
                const endX = this.canvas.width * 0.8;
                const endY = this.canvas.height * 0.5;

                // 生成主要路径
                const pathPoints = this.generatePath(startX, startY, endX, endY, 5 + this.currentLevel * 2);
                
                // 根据路径生成墙壁
                for (let i = 0; i < pathPoints.length - 1; i++) {
                    const current = pathPoints[i];
                    const next = pathPoints[i + 1];
                    
                    const isNearStart = this.isPointInSafeZone(current.x, current.y, startX, startY, safeRadius);
                    const isNearEnd = this.isPointInSafeZone(current.x, current.y, endX, endY, safeRadius);
                    
                    if (!isNearStart && !isNearEnd && Math.random() > 0.3) {
                        const isVertical = Math.abs(next.x - current.x) < Math.abs(next.y - current.y);
                        const wallLength = 60 + Math.random() * 60;
                        
                        if (isVertical) {
                            this.walls.push({
                                x: current.x - wallLength/2,
                                y: current.y - 10,
                                width: wallLength,
                                height: 15
                            });
                        } else {
                            this.walls.push({
                                x: current.x - 10,
                                y: current.y - wallLength/2,
                                width: 15,
                                height: wallLength
                            });
                        }
                    }
                }

                // 添加额外的随机墙壁
                const numWalls = 5 + this.currentLevel * 2;
                for (let i = 0; i < numWalls; i++) {
                    let x, y;
                    let attempts = 0;
                    const maxAttempts = 50;

                    do {
                        x = 100 + Math.random() * (this.canvas.width - 200);
                        y = 100 + Math.random() * (this.canvas.height - 200);
                        attempts++;
                    } while (
                        (this.isPointInSafeZone(x, y, startX, startY, safeRadius) ||
                         this.isPointInSafeZone(x, y, endX, endY, safeRadius) ||
                         this.isTooCloseToPath(x, y, pathPoints, 40)) &&
                        attempts < maxAttempts
                    );

                    if (attempts < maxAttempts) {
                        const isVertical = Math.random() > 0.5;
                        const wallLength = 60 + Math.random() * 60;
                        
                        this.walls.push({
                            x: x,
                            y: y,
                            width: isVertical ? 15 : wallLength,
                            height: isVertical ? wallLength : 15
                        });
                    }
                }

                // 生成重力场
                const numFields = 2 + this.currentLevel;
                const gravityFieldRadius = 30;
                const minDistanceFromStart = 100;
                
                for (let i = 0; i < numFields; i++) {
                    let x, y;
                    let attempts = 0;
                    const maxAttempts = 50;

                    do {
                        x = 150 + Math.random() * (this.canvas.width - 300);
                        y = 150 + Math.random() * (this.canvas.height - 300);
                        attempts++;

                        const isInSafeZone = this.isPointInSafeZone(x, y, startX, startY, safeRadius) ||
                                           this.isPointInSafeZone(x, y, endX, endY, safeRadius);

                        const dx = x - startX;
                        const dy = y - startY;
                        const distanceFromStart = Math.sqrt(dx * dx + dy * dy);

                        const isOverlapping = this.gravityFields.some(field => {
                            const fieldDx = x - (field.x + field.width/2);
                            const fieldDy = y - (field.y + field.height/2);
                            const distance = Math.sqrt(fieldDx * fieldDx + fieldDy * fieldDy);
                            return distance < gravityFieldRadius * 2;
                        });

                        if (!isInSafeZone && 
                            distanceFromStart >= minDistanceFromStart && 
                            !isOverlapping && 
                            !this.isTooCloseToPath(x, y, pathPoints, 40)) {
                            break;
                        }
                    } while (attempts < maxAttempts);

                    if (attempts < maxAttempts) {
                        this.gravityFields.push({
                            x: x,
                            y: y,
                            width: 60,
                            height: 60,
                            gravity: {
                                x: Math.random() > 0.5 ? (Math.random() > 0.5 ? 1 : -1) : 0,
                                y: Math.random() > 0.5 ? (Math.random() > 0.5 ? 1 : -1) : 0
                            },
                            strength: 1.5 + Math.random()
                        });
                    }
                }

                // 设置小球初始位置
                this.ball.reset(startX, startY);
                this.goal = {
                    x: endX,
                    y: endY,
                    radius: 20
                };
            }

            generatePath(startX, startY, endX, endY, numPoints) {
                const points = [{x: startX, y: startY}];
                const stepX = (endX - startX) / (numPoints + 1);
                const stepY = (endY - startY) / (numPoints + 1);

                for (let i = 1; i <= numPoints; i++) {
                    const baseX = startX + stepX * i;
                    const baseY = startY + stepY * i;
                    
                    // 添加随机偏移
                    const offsetX = (Math.random() - 0.5) * 100;
                    const offsetY = (Math.random() - 0.5) * 100;
                    
                    points.push({
                        x: baseX + offsetX,
                        y: baseY + offsetY
                    });
                }
                
                points.push({x: endX, y: endY});
                return points;
            }

            isTooCloseToPath(x, y, pathPoints, minGap) {
                for (const point of pathPoints) {
                    const dx = x - point.x;
                    const dy = y - point.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    if (distance < minGap) return true;
                }
                return false;
            }

            isPointInSafeZone(x, y, centerX, centerY, radius) {
                const dx = x - centerX;
                const dy = y - centerY;
                return Math.sqrt(dx * dx + dy * dy) < radius;
            }

            startGame() {
                this.uiElements.startMenu.style.display = 'none';
                this.resetGame();
            }

            resetGame() {
                this.gravity = { x: 0, y: 1 };
                this.flipsRemaining = this.calculateInitialFlips();
                this.isGameOver = false;
                this.trail = [];
                this.lastFlipTime = 0;

                // 记录尝试次数
                if (!this.isFirstAttempt) {
                    this.levelAttempts++;
                }
                this.isFirstAttempt = false;

                // 记录开始时间
                this.levelStartTime = performance.now();

                this.uiElements.flips.textContent = this.flipsRemaining;
                this.uiElements.level.textContent = this.currentLevel;
                this.uiElements.gameOver.style.display = 'none';

                this.updateGravityDisplay();

                this.ball.reset(this.canvas.width * 0.2, this.canvas.height * 0.5);
                this.generateLevel();

                this.timeRemaining = this.timeLimit;
                this.lastTimeUpdate = performance.now();
                this.timeDisplay.querySelector('span').textContent = '2:00';

                this.lastTime = performance.now();
                this.gameLoop();
            }

            nextLevel() {
                if (this.currentLevel < this.maxLevels) {
                    this.currentLevel++;
                    // 重置关卡相关数据
                    this.levelStartTime = 0;
                    this.totalLevelTime = 0;
                    this.levelAttempts = 0;
                    this.isFirstAttempt = true;
                    this.resetGame();
                } else {
                    this.uiElements.gameOver.style.display = 'none';
                    this.uiElements.startMenu.style.display = 'block';
                    this.currentLevel = 1;
                    this.passedLevels = 0;
                }
            }

            calculateInitialFlips() {
                return Math.max(5, 30 - (this.currentLevel - 1) * 5);
            }

            update(deltaTime) {
                if (this.isGameOver) return;

                // 更新时间
                const now = performance.now();
                if (now - this.lastTimeUpdate >= 1000) {
                    this.timeRemaining--;
                    this.lastTimeUpdate = now;
                    
                    // 更新时间显示
                    const minutes = Math.floor(this.timeRemaining / 60);
                    const seconds = this.timeRemaining % 60;
                    this.timeDisplay.querySelector('span').textContent = 
                        `${minutes}:${seconds.toString().padStart(2, '0')}`;
                    
                    if (this.timeRemaining <= 0) {
                        this.isGameOver = true;
                        SOUNDS.gameOver.play();
                        this.uiElements.resultTitle.textContent = "时间到!";
                        this.uiElements.passedLevels.textContent = this.passedLevels;
                        this.uiElements.gameOver.style.display = 'block';
                        return;
                    }
                }

                this.ball.applyGravity(this.gravity);
                this.ball.update(deltaTime);
                this.checkCollisions();
            }

            draw() {
                this.ctx.fillStyle = '#111122';
                this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);

                this.drawGoal();
                this.drawWalls();
                this.drawGravityFields();
                this.ball.draw(this.ctx);
                this.drawGravityIndicator();
            }

            gameLoop() {
                const now = performance.now();
                const deltaTime = (now - this.lastTime) / 1000;
                this.lastTime = now;

                this.update(deltaTime);
                this.draw();

                requestAnimationFrame(() => this.gameLoop());
            }

            handleInput(e) {
                if (this.isGameOver) return;

                if (e.key === ' ') {
                    if (this.ball.isStopped) {
                        // 小球初始运动
                        this.ball.isStopped = false;
                        this.ball.applyGravity(this.gravity);
                        SOUNDS.flip.play();
                    } else {
                        if (this.flipsRemaining > 0 && performance.now() - this.lastFlipTime > 500) {
                            this.flipsRemaining--;
                            this.lastFlipTime = performance.now();
                            this.uiElements.flips.textContent = this.flipsRemaining;

                            if (this.gravity.y === 1) this.gravity = { x: 1, y: 0 };
                            else if (this.gravity.x === 1) this.gravity = { x: 0, y: -1 };
                            else if (this.gravity.y === -1) this.gravity = { x: -1, y: 0 };
                            else this.gravity = { x: 0, y: 1 };

                            this.updateGravityDisplay();
                            this.createFlipEffect();
                            SOUNDS.flip.play();
                        }
                    }
                }
            }

            checkCollisions() {
                for (const wall of this.walls) {
                    if (this.ball.collidesWithWall(wall)) {
                        this.isGameOver = true;
                        SOUNDS.hit.play();
                        this.uiElements.resultTitle.textContent = "游戏结束!";
                        this.uiElements.passedLevels.textContent = this.passedLevels;
                        this.uiElements.gameOver.style.display = 'block';
                        this.trail = [];
                        return;
                    }
                }

                for (const field of this.gravityFields) {
                    if (this.ball.collidesWithRect(field)) {
                        const baseSpeed = 4 * field.strength;
                        
                        // 立即设置新的速度，不考虑原有速度
                        if (field.gravity.x > 0) {
                            this.ball.velocity.x = baseSpeed;
                            this.ball.velocity.y = 0;
                        } else if (field.gravity.x < 0) {
                            this.ball.velocity.x = -baseSpeed;
                            this.ball.velocity.y = 0;
                        } else if (field.gravity.y > 0) {
                            this.ball.velocity.x = 0;
                            this.ball.velocity.y = baseSpeed;
                        } else if (field.gravity.y < 0) {
                            this.ball.velocity.x = 0;
                            this.ball.velocity.y = -baseSpeed;
                        }
                        
                        // 更新重力方向并立即应用
                        this.gravity = { ...field.gravity };
                        this.ball.applyGravity(this.gravity, field.strength);
                        this.updateGravityDisplay();
                        this.createFlipEffect();
                        this.ball.isStopped = false;
                        break;
                    }
                }

                const dx = this.ball.x - this.goal.x;
                const dy = this.ball.y - this.goal.y;
                const distance = Math.sqrt(dx * dx + dy * dy);

                if (distance < this.ball.radius + this.goal.radius) {
                    this.isGameOver = true;
                    this.passedLevels = this.currentLevel;
                    SOUNDS.goal.play();

                    // 计算总通关时间
                    const currentTime = performance.now();
                    const levelTime = (currentTime - this.levelStartTime) / 1000; // 转换为秒
                    this.totalLevelTime += levelTime;

                    const history = JSON.parse(localStorage.getItem('gravityMazeHistory') || '{}');
                    history[this.currentLevel] = {
                        flipsRemaining: this.flipsRemaining,
                        time: Math.floor(this.totalLevelTime),
                        attempts: this.levelAttempts + 1
                    };
                    localStorage.setItem('gravityMazeHistory', JSON.stringify(history));

                    this.uiElements.resultTitle.textContent = "关卡完成!";
                    this.uiElements.passedLevels.textContent = this.passedLevels;
                    this.uiElements.gameOver.style.display = 'block';

                    if (this.currentLevel < this.maxLevels) {
                        this.uiElements.resultTitle.textContent = "关卡完成!";
                    } else {
                        this.uiElements.resultTitle.textContent = "全部通关！";
                    }
                }

                if (this.flipsRemaining <= 0 &&
                    Math.abs(this.ball.velocity.x) < 0.3 &&
                    Math.abs(this.ball.velocity.y) < 0.3) {
                    this.isGameOver = true;
                    SOUNDS.gameOver.play();
                    this.uiElements.resultTitle.textContent = "游戏结束!";
                    this.uiElements.passedLevels.textContent = this.passedLevels;
                    this.uiElements.gameOver.style.display = 'block';
                }
            }

            drawGoal() {
                this.ctx.fillStyle = COLORS.goal;
                this.ctx.beginPath();
                this.ctx.arc(this.goal.x, this.goal.y, this.goal.radius, 0, Math.PI * 2);
                this.ctx.fill();
            }

            drawWalls() {
                this.ctx.fillStyle = '#334466';
                for (const wall of this.walls) {
                    // 添加渐变效果
                    const gradient = this.ctx.createLinearGradient(
                        wall.x, wall.y,
                        wall.x + wall.width, wall.y + wall.height
                    );
                    gradient.addColorStop(0, '#334466');
                    gradient.addColorStop(1, '#445577');
                    this.ctx.fillStyle = gradient;
                    
                    // 添加圆角
                    this.ctx.beginPath();
                    this.ctx.roundRect(wall.x, wall.y, wall.width, wall.height, 5);
                    this.ctx.fill();
                    
                    // 添加高光效果
                    this.ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
                    this.ctx.lineWidth = 2;
                    this.ctx.stroke();
                }
            }

            drawGravityFields() {
                for (const field of this.gravityFields) {
                    // 绘制半透明背景
                    this.ctx.fillStyle = 'rgba(255, 170, 51, 0.2)';
                    this.ctx.beginPath();
                    this.ctx.roundRect(field.x, field.y, field.width, field.height, 8);
                    this.ctx.fill();

                    // 绘制边框
                    this.ctx.strokeStyle = 'rgba(255, 170, 51, 0.5)';
                    this.ctx.lineWidth = 2;
                    this.ctx.stroke();

                    // 绘制方向箭头
                    const centerX = field.x + field.width / 2;
                    const centerY = field.y + field.height / 2;
                    this.drawArrow(centerX, centerY, field.gravity);
                }
            }

            drawArrow(x, y, direction) {
                const length = 25;
                const headSize = 10;
                let endX = x, endY = y;

                if (direction.x > 0) endX += length;
                else if (direction.x < 0) endX -= length;
                else if (direction.y > 0) endY += length;
                else endY -= length;

                // 绘制箭头主体
                this.ctx.beginPath();
                this.ctx.moveTo(x, y);
                this.ctx.lineTo(endX, endY);
                this.ctx.lineWidth = 3;
                this.ctx.strokeStyle = 'rgba(255, 170, 51, 0.8)';
                this.ctx.stroke();

                // 绘制箭头头部
                this.ctx.beginPath();
                if (direction.x !== 0) {
                    this.ctx.moveTo(endX, endY - headSize / 2);
                    this.ctx.lineTo(endX, endY + headSize / 2);
                    this.ctx.lineTo(endX + (direction.x > 0 ? headSize : -headSize), endY);
                } else {
                    this.ctx.moveTo(endX - headSize / 2, endY);
                    this.ctx.lineTo(endX + headSize / 2, endY);
                    this.ctx.lineTo(endX, endY + (direction.y > 0 ? headSize : -headSize));
                }
                this.ctx.closePath();
                this.ctx.fillStyle = 'rgba(255, 170, 51, 0.8)';
                this.ctx.fill();
            }

            drawTrail() {
                // 移除轨迹绘制
            }

            drawGravityIndicator() {
                const size = 30;
                const margin = 40;
                const x = this.canvas.width - margin;
                const y = margin;

                this.ctx.save();
                this.ctx.translate(x, y);

                this.ctx.fillStyle = 'rgba(0,0,0,0.5)';
                this.ctx.beginPath();
                this.ctx.arc(0, 0, size / 2, 0, Math.PI * 2);
                this.ctx.fill();

                this.ctx.fillStyle = '#FF5555';
                this.ctx.beginPath();

                if (this.gravity.y > 0) {
                    this.ctx.moveTo(0, size / 3);
                    this.ctx.lineTo(-size / 4, -size / 6);
                    this.ctx.lineTo(size / 4, -size / 6);
                } else if (this.gravity.y < 0) {
                    this.ctx.moveTo(0, -size / 3);
                    this.ctx.lineTo(-size / 4, size / 6);
                    this.ctx.lineTo(size / 4, size / 6);
                } else if (this.gravity.x > 0) {
                    this.ctx.moveTo(size / 3, 0);
                    this.ctx.lineTo(-size / 6, -size / 4);
                    this.ctx.lineTo(-size / 6, size / 4);
                } else if (this.gravity.x < 0) {
                    this.ctx.moveTo(-size / 3, 0);
                    this.ctx.lineTo(size / 6, -size / 4);
                    this.ctx.lineTo(size / 6, size / 4);
                }

                this.ctx.closePath();
                this.ctx.fill();
                this.ctx.restore();
            }

            updateGravityDisplay() {
                let displayChar = '↓';
                if (this.gravity.y < 0) displayChar = '↑';
                else if (this.gravity.x > 0) displayChar = '→';
                else if (this.gravity.x < 0) displayChar = '←';

                this.uiElements.gravity.textContent = displayChar;
                this.uiElements.gravity.style.color = '#FF5555';
            }

            createFlipEffect() {
                // 移除翻转特效
            }

            exitGame() {
                this.uiElements.gameOver.style.display = 'none';
                this.uiElements.startMenu.style.display = 'block';

                // 直接调用 showChart，它会使用 this.passedLevels
                this.showChart();
            }

            showChart() {
                const chartContainer = document.createElement('div');
                chartContainer.id = 'chart';
                chartContainer.style.position = 'absolute';
                chartContainer.style.top = '10%';
                chartContainer.style.left = '50%';
                chartContainer.style.transform = 'translateX(-50%)';
                chartContainer.style.width = '80%';
                chartContainer.style.height = '500px';
                chartContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
                chartContainer.style.borderRadius = '15px';
                chartContainer.style.border = '2px solid rgba(255, 85, 85, 0.3)';
                chartContainer.style.boxShadow = '0 0 20px rgba(255, 85, 85, 0.2)';
                chartContainer.style.zIndex = '1000';
                chartContainer.style.padding = '20px';
                document.body.appendChild(chartContainer);

                const myChart = echarts.init(chartContainer);

                // 准备数据
                const history = JSON.parse(localStorage.getItem('gravityMazeHistory') || '{}');
                const currentLevel = this.passedLevels || 1;
                
                // 创建从1到当前关卡的数据数组
                const levels = [];
                const flipsData = [];
                const timeData = [];
                const attemptsData = [];

                // 遍历每一关，收集数据
                for (let level = 1; level <= currentLevel; level++) {
                    levels.push(level);
                    
                    // 获取该关卡初始的反转次数
                    const initialFlips = Math.max(5, 30 - (level - 1) * 5);
                    
                    // 获取实际保存的数据
                    const levelData = history[level] || { flipsRemaining: initialFlips, time: 0, attempts: 0 };
                    
                    // 计算使用次数：初始次数 - 剩余次数
                    const usedFlips = initialFlips - levelData.flipsRemaining;
                    flipsData.push(usedFlips);
                    
                    // 使用实际记录的时间
                    timeData.push(levelData.time);
                    
                    // 使用实际记录的尝试次数
                    attemptsData.push(levelData.attempts);
                }

                const option = {
                    backgroundColor: 'transparent',
                    title: {
                        text: '游戏数据统计',
                        left: 'center',
                        textStyle: {
                            color: '#FF5555',
                            fontSize: 24,
                            fontWeight: 'bold',
                            textShadow: '0 0 10px rgba(255, 85, 85, 0.5)'
                        }
                    },
                    tooltip: {
                        trigger: 'axis',
                        axisPointer: {
                            type: 'shadow',
                            shadowStyle: {
                                color: 'rgba(255, 85, 85, 0.1)'
                            }
                        },
                        backgroundColor: 'rgba(0, 0, 0, 0.8)',
                        borderColor: '#FF5555',
                        borderWidth: 1,
                        textStyle: {
                            color: '#fff'
                        }
                    },
                    legend: {
                        data: ['使用次数', '通关时间(秒)', '尝试次数'],
                        textStyle: {
                            color: '#fff'
                        },
                        top: 40
                    },
                    grid: {
                        left: '3%',
                        right: '4%',
                        bottom: '3%',
                        containLabel: true
                    },
                    xAxis: {
                        type: 'category',
                        data: levels.map(level => `第${level}关`),
                        axisLine: {
                            lineStyle: {
                                color: '#FF5555'
                            }
                        },
                        axisLabel: {
                            color: '#fff',
                            rotate: 45
                        }
                    },
                    yAxis: [
                        {
                            type: 'value',
                            name: '数值',
                            nameTextStyle: {
                                color: '#fff'
                            },
                            axisLine: {
                                lineStyle: {
                                    color: '#FF5555'
                                }
                            },
                            axisLabel: {
                                color: '#fff'
                            },
                            splitLine: {
                                lineStyle: {
                                    color: 'rgba(255, 85, 85, 0.1)'
                                }
                            }
                        }
                    ],
                    series: [
                        {
                            name: '使用次数',
                            type: 'bar',
                            data: flipsData,
                            itemStyle: {
                                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                                    { offset: 0, color: '#FF5555' },
                                    { offset: 1, color: '#FF8888' }
                                ])
                            },
                            barWidth: '20%',
                            emphasis: {
                                itemStyle: {
                                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                                        { offset: 0, color: '#FF8888' },
                                        { offset: 1, color: '#FF5555' }
                                    ])
                                }
                            }
                        },
                        {
                            name: '通关时间(秒)',
                            type: 'line',
                            data: timeData,
                            symbol: 'circle',
                            symbolSize: 8,
                            lineStyle: {
                                color: '#55FF55',
                                width: 3
                            },
                            itemStyle: {
                                color: '#55FF55',
                                borderColor: '#fff',
                                borderWidth: 2
                            }
                        },
                        {
                            name: '尝试次数',
                            type: 'line',
                            data: attemptsData,
                            symbol: 'diamond',
                            symbolSize: 10,
                            lineStyle: {
                                color: '#5555FF',
                                width: 3
                            },
                            itemStyle: {
                                color: '#5555FF',
                                borderColor: '#fff',
                                borderWidth: 2
                            }
                        }
                    ],
                    animation: true,
                    animationDuration: 2000,
                    animationEasing: 'cubicInOut'
                };

                myChart.setOption(option);

                // 添加关闭按钮
                const closeBtn = document.createElement('button');
                closeBtn.innerText = '关闭图表';
                closeBtn.style.position = 'absolute';
                closeBtn.style.top = '20px';
                closeBtn.style.right = '20px';
                closeBtn.style.padding = '10px 20px';
                closeBtn.style.background = '#FF5555';
                closeBtn.style.color = 'white';
                closeBtn.style.border = 'none';
                closeBtn.style.borderRadius = '5px';
                closeBtn.style.cursor = 'pointer';
                closeBtn.style.fontSize = '16px';
                closeBtn.style.transition = 'all 0.3s ease';
                closeBtn.style.boxShadow = '0 0 10px rgba(255, 85, 85, 0.3)';

                closeBtn.onmouseover = () => {
                    closeBtn.style.background = '#FF3333';
                    closeBtn.style.transform = 'translateY(-2px)';
                    closeBtn.style.boxShadow = '0 0 15px rgba(255, 85, 85, 0.5)';
                };

                closeBtn.onmouseout = () => {
                    closeBtn.style.background = '#FF5555';
                    closeBtn.style.transform = 'translateY(0)';
                    closeBtn.style.boxShadow = '0 0 10px rgba(255, 85, 85, 0.3)';
                };

                closeBtn.onclick = () => {
                    document.body.removeChild(chartContainer);
                    document.body.removeChild(closeBtn);
                };

                document.body.appendChild(closeBtn);

                // 添加窗口大小改变时的自适应
                window.addEventListener('resize', () => {
                    myChart.resize();
                });
            }
        }

        class Ball {
            constructor(x, y, radius) {
                this.reset(x, y);
                this.radius = radius;
                this.baseColor = COLORS.ball;
                this.lastGravityField = null;
            }

            reset(x, y) {
                this.x = x;
                this.y = y;
                this.velocity = { x: 0, y: 0 };
                this.isStopped = true;
                this.lastGravityField = null;
            }

            applyGravity(gravity, multiplier = 1) {
                if (this.isStopped) return; // 如果小球是静止的，不应用重力

                const baseSpeed = 4 * multiplier;

                // 立即设置新的速度，不考虑原有状态
                if (gravity.x > 0) {
                    this.velocity.x = baseSpeed;
                    this.velocity.y = 0;
                } else if (gravity.x < 0) {
                    this.velocity.x = -baseSpeed;
                    this.velocity.y = 0;
                } else if (gravity.y > 0) {
                    this.velocity.x = 0;
                    this.velocity.y = baseSpeed;
                } else if (gravity.y < 0) {
                    this.velocity.x = 0;
                    this.velocity.y = -baseSpeed;
                }
            }

            update(deltaTime) {
                if (this.isStopped) return; // 如果小球是静止的，不更新位置

                // 只限制最大速度
                const maxSpeed = 8.0;
                const currentSpeed = Math.sqrt(this.velocity.x * this.velocity.x + this.velocity.y * this.velocity.y);
                
                if (currentSpeed > maxSpeed) {
                    const scale = maxSpeed / currentSpeed;
                    this.velocity.x *= scale;
                    this.velocity.y *= scale;
                }
                
                this.x += this.velocity.x * deltaTime * 60;
                this.y += this.velocity.y * deltaTime * 60;
                
                // 使用更小的阻尼系数，减少速度衰减
                const damping = 0.9995;
                this.velocity.x *= damping;
                this.velocity.y *= damping;
            }

            draw(ctx) {
                const gradient = ctx.createRadialGradient(
                    this.x - this.radius * 0.3,
                    this.y - this.radius * 0.3,
                    0,
                    this.x,
                    this.y,
                    this.radius
                );
                gradient.addColorStop(0, '#FF8888');
                gradient.addColorStop(1, this.baseColor);
                ctx.fillStyle = gradient;
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
                ctx.fill();

                ctx.fillStyle = 'rgba(255,255,255,0.4)';
                ctx.beginPath();
                ctx.arc(this.x - this.radius * 0.2, this.y - this.radius * 0.2, this.radius * 0.3, 0, Math.PI * 2);
                ctx.fill();
            }

            collidesWithWall(wall) {
                const closestX = Math.max(wall.x, Math.min(this.x, wall.x + wall.width));
                const closestY = Math.max(wall.y, Math.min(this.y, wall.y + wall.height));
                const dx = this.x - closestX;
                const dy = this.y - closestY;
                return dx * dx + dy * dy < this.radius * this.radius;
            }

            collidesWithRect(rect) {
                const closestX = Math.max(rect.x, Math.min(this.x, rect.x + rect.width));
                const closestY = Math.max(rect.y, Math.min(this.y, rect.y + rect.height));
                const dx = this.x - closestX;
                const dy = this.y - closestY;
                return dx * dx + dy * dy < this.radius * this.radius;
            }
        }

        window.onload = () => new GravityMaze();
    </script>
</body>

</html>